package com.dsl.dslallinone.core;

import com.dsl.dslallinone.common.config.FilterConfig;
import com.dsl.dslallinone.dto.DslQuery;
import com.dsl.dslallinone.dto.DslQueryResponse;
import com.dsl.dslallinone.dto.Granularity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 实时数据路由器
 * 从Redis Hash读取实时数据并进行缺失值补齐
 */
@Component
public class RealtimeRouter {
    private static final Logger logger = LoggerFactory.getLogger(RealtimeRouter.class);

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Value("${dsl.realtime.redis-key-prefix:realtime:}")
    private String redisKeyPrefix;

    @Value("${dsl.realtime.default-fill-missing:zero}")
    private String defaultFillMissing;

    /**
     * 执行实时查询
     */
    public DslQueryResponse executeQuery(DslQuery query) {
        logger.info("执行实时数据查询");

        // 解析查询范围
        String scope = extractScope(query);
        List<String> ids = extractIds(query);

        // 读取Redis数据
        List<Map<String, Object>> rawData = readRealtimeData(scope, ids);

        // 补齐缺失数据
        List<Map<String, Object>> filledData = fillMissingData(rawData, query);

        // 构建响应
        return buildRealtimeResponse(query, filledData);
    }

    /**
     * 从查询中提取范围（building/floor/device）
     */
    private String extractScope(DslQuery query) {
        if (query.getGroupBy() != null && !query.getGroupBy().isEmpty()) {
            String groupField = query.getGroupBy().get(0);
            if (groupField.contains("building")) return "building";
            if (groupField.contains("floor")) return "floor";
            if (groupField.contains("device")) return "device";
        }
        return "floor"; // 默认按楼层
    }

    /**
     * 从查询中提取ID列表
     */
    private List<String> extractIds(DslQuery query) {
        List<String> ids = new ArrayList<>();
        
        if (query.getFilter() != null) {
            for (FilterConfig filter : query.getFilter()) {
                if (filter.getField().endsWith("_id")) {
                    if (filter.getValue() instanceof List) {
                        List<?> values = (List<?>) filter.getValue();
                        ids.addAll(values.stream().map(String::valueOf).collect(Collectors.toList()));
                    } else {
                        ids.add(String.valueOf(filter.getValue()));
                    }
                }
            }
        }

        // 如果没有指定ID，使用默认值
        if (ids.isEmpty()) {
            ids.addAll(Arrays.asList("101", "102", "103"));
        }

        return ids;
    }

    /**
     * 读取实时数据
     * Redis Hash结构: key=realtime:{scope}:{id}, fields=online,occupied,power,liquid_level,ts
     */
    private List<Map<String, Object>> readRealtimeData(String scope, List<String> ids) {
        List<Map<String, Object>> data = new ArrayList<>();

        for (String id : ids) {
            String redisKey = redisKeyPrefix + scope + ":" + id;
            Map<Object, Object> hashData = stringRedisTemplate.opsForHash().entries(redisKey);

            if (!hashData.isEmpty()) {
                Map<String, Object> record = new HashMap<>();
                record.put(scope + "_id", id);
                record.put("online", parseDouble(hashData.get("online")));
                record.put("occupied", parseDouble(hashData.get("occupied")));
                record.put("power", parseDouble(hashData.get("power")));
                record.put("liquid_level", parseDouble(hashData.get("liquid_level")));
                record.put("ts", String.valueOf(hashData.get("ts")));
                data.add(record);
            } else {
                logger.warn("Redis中未找到key: {}", redisKey);
                // 创建空记录用于后续补齐
                Map<String, Object> record = new HashMap<>();
                record.put(scope + "_id", id);
                data.add(record);
            }
        }

        return data;
    }

    /**
     * 补齐缺失数据
     */
    private List<Map<String, Object>> fillMissingData(List<Map<String, Object>> rawData, DslQuery query) {
        String fillStrategy = defaultFillMissing;
        if (query.getPost() != null && query.getPost().getFillMissing() != null) {
            fillStrategy = query.getPost().getFillMissing();
        }

        List<Map<String, Object>> filledData = new ArrayList<>();

        // 如果是小时粒度，需要补齐24小时数据
        if (query.getTime().getGranularity() == Granularity.HOUR) {
            filledData = fillHourlyData(rawData, query, fillStrategy);
        } else {
            filledData = fillBasicData(rawData, fillStrategy);
        }

        return filledData;
    }

    /**
     * 补齐小时数据（0-23小时）
     */
    private List<Map<String, Object>> fillHourlyData(List<Map<String, Object>> rawData, DslQuery query, String fillStrategy) {
        List<Map<String, Object>> result = new ArrayList<>();
        LocalDate queryDate = query.getTime().getWindow().getStart();

        for (Map<String, Object> record : rawData) {
            for (int hour = 0; hour < 24; hour++) {
                Map<String, Object> hourRecord = new HashMap<>(record);
                String timeBucket = queryDate.atTime(hour, 0).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                hourRecord.put("time_bucket", timeBucket);

                // 补齐缺失字段
                fillMissingFields(hourRecord, fillStrategy);
                result.add(hourRecord);
            }
        }

        return result;
    }

    /**
     * 补齐基础数据
     */
    private List<Map<String, Object>> fillBasicData(List<Map<String, Object>> rawData, String fillStrategy) {
        for (Map<String, Object> record : rawData) {
            fillMissingFields(record, fillStrategy);
        }
        return rawData;
    }

    /**
     * 补齐缺失字段
     */
    private void fillMissingFields(Map<String, Object> record, String fillStrategy) {
        String[] fields = {"online", "occupied", "power", "liquid_level"};

        for (String field : fields) {
            if (!record.containsKey(field) || record.get(field) == null) {
                switch (fillStrategy.toLowerCase()) {
                    case "zero":
                        record.put(field, 0.0);
                        break;
                    case "forward":
                        // 简化实现：使用前一个值（这里用0代替）
                        record.put(field, 0.0);
                        break;
                    case "backward":
                        // 简化实现：使用后一个值（这里用0代替）
                        record.put(field, 0.0);
                        break;
                    default:
                        record.put(field, 0.0);
                }
            }
        }

        // 补齐时间戳
        if (!record.containsKey("ts") || record.get("ts") == null) {
            record.put("ts", System.currentTimeMillis());
        }
    }

    /**
     * 构建实时查询响应
     */
    private DslQueryResponse buildRealtimeResponse(DslQuery query, List<Map<String, Object>> data) {
        // 构建series数据
        List<DslQueryResponse.SeriesData> series = buildRealtimeSeries(data, query);

        // 构建table数据
        DslQueryResponse.TableData table = buildRealtimeTable(data);

        // 构建meta数据
        DslQueryResponse.MetaData meta = new DslQueryResponse.MetaData(
                query.getTime().getGranularity(),
                query.getTime().getWindow(),
                "%", // 实时数据单位通常是百分比
                "realtime"
        );

        return new DslQueryResponse(series, table, meta);
    }

    /**
     * 构建实时series数据
     */
    private List<DslQueryResponse.SeriesData> buildRealtimeSeries(List<Map<String, Object>> data, DslQuery query) {
        List<DslQueryResponse.SeriesData> series = new ArrayList<>();

        // 按ID分组
        Map<String, List<Map<String, Object>>> grouped = data.stream()
                .collect(Collectors.groupingBy(record -> {
                    String scope = extractScope(query);
                    return String.valueOf(record.get(scope + "_id"));
                }));

        for (Map.Entry<String, List<Map<String, Object>>> entry : grouped.entrySet()) {
            String seriesName = extractScope(query) + "=" + entry.getKey();
            series.add(new DslQueryResponse.SeriesData(seriesName, entry.getValue()));
        }

        return series;
    }

    /**
     * 构建实时table数据
     */
    private DslQueryResponse.TableData buildRealtimeTable(List<Map<String, Object>> data) {
        if (data.isEmpty()) {
            return new DslQueryResponse.TableData(new ArrayList<>(), new ArrayList<>());
        }

        // 获取列名
        List<String> columns = new ArrayList<>(data.get(0).keySet());

        // 构建行数据
        List<List<Object>> rows = new ArrayList<>();
        for (Map<String, Object> record : data) {
            List<Object> row = new ArrayList<>();
            for (String column : columns) {
                row.add(record.get(column));
            }
            rows.add(row);
        }

        return new DslQueryResponse.TableData(columns, rows);
    }

    /**
     * 解析Double值
     */
    private Double parseDouble(Object value) {
        if (value == null) return null;
        try {
            return Double.parseDouble(String.valueOf(value));
        } catch (NumberFormatException e) {
            return 0.0;
        }
    }
}
